<!-- HTML header for doxygen 1.8.3.1-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.3.1"/>
<title>Sifteo SDK: Graphics Engine</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="doxygen-style-overrides.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<center>
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Sifteo SDK" src="sdk_logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">
   &#160;<span id="projectnumber">v1.0.0</span>
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
</center>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.3.1 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Home</span></a></li>
      <li class="current"><a href="pages.html"><span>Guides</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Reference</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Namespaces</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Groups</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Graphics Engine </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>Details on the Sifteo graphical architecture</p>
<h1>Overview</h1>
<p>Sifteo cubes have a fairly unique graphics architecture. This section introduces the main differences you'll notice between Sifteo cubes and other systems you may be familiar with. We assume at least some basic familiarity with computer architecture and computer graphics.</p>
<h2>Display</h2>
<div class="image">
<img src="single-cube.png" alt="single-cube.png"/>
</div>
<p>The display on each Sifteo Cube is the star of the show. It's what sets Sifteo Cubes apart from dominos, Mahjongg tiles, and most other tiny objects people love to pick up and touch and play with.</p>
<p>Our displays are 128x128 pixels, with a color depth of 16 bits per pixel. This format is often called <b>RGB565</b>, since it uses 5 bits of information each to store the Red and Blue channels of each pixel, and 6 bits for Green. (The human eye is most sensitive to green, so we can certainly use an extra bit there!)</p>
<p>This RGB565 color representation is used pervasively throughout the Sifteo SDK and <a class="el" href="asset_workflow.html">Asset Preparation</a> toolchain. To get the best quality results, we always recommend that you start with lossless true-color images. The asset tools will automatically perform various kinds of lossless and optionally lossy compression on these images, and any existing lossy compression will simply hinder these compression passes. Your images won't be looking their best, and they will take up more space! Yuck!</p>
<p>In particular, here are some tips for preparing graphics to use with the Sifteo SDK:</p>
<ul>
<li><b>Never use JPEG</b> images, or images that have been previously stored as JPEG. Always start with images in a lossless format like PNG or PSD.</li>
<li><b>Never dither</b> your images! Dithered images are harder to compress, so they will take up more space and they won't look as good.</li>
<li>Keep your graphics <b>big</b>. Each cube has a small display, and you shouldn't clutter it with too many things at once.</li>
<li>Keep your graphics <b>vibrant</b>. The gamma curve of the display may change as the viewing angle changes during play, so be sure to use enough visual contrast.</li>
<li>Use <b>animation and interactivity</b> whenever you can. More interactivity equals more fun, and Sifteo Cubes are great at fluid animation.</li>
<li>Use stir's <b>proof output</b> or <b>siftulator</b> if you want to see exactly how your images will look in-game.</li>
</ul>
<h2>Distributed Rendering</h2>
<p>Unlike most game systems, the display is not directly attached to the hardware your application runs on. For this reason, Sifteo cubes use a <em>distributed rendering</em> architecture:</p>
<div class="image">
<img src="distributed-rendering.png" alt="distributed-rendering.png"/>
</div>
<p>Each cube has its own graphics engine hardware, display hardware, and storage. Cubes have two types of local memory:</p>
<ul>
<li><b>Asset Flash</b><ul>
<li>It is relatively large (several megabytes).</li>
<li>It is very fast to draw from, but very slow to rewrite.</li>
<li>It contains uncompressed 16-bit pixel data, arranged in 8x8-pixel tiles.</li>
</ul>
</li>
</ul>
<ul>
<li><b>Video RAM</b><ul>
<li>It is tiny (1 kilobyte).</li>
<li>It is fast both to read and to write.</li>
<li>It contains metadata and commands, typically no pixel data.</li>
<li>It orchestrates the process of drawing a scene or part of a scene to the display.</li>
<li>Applications keep a shadow copy of this memory in a <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a> object.</li>
<li>The system continuously synchronizes each cube's Video RAM with any correspondingly attached <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</li>
</ul>
</li>
</ul>
<h2>Concurrency</h2>
<p>This distributed architecture implies that many rendering operations are inherently <b>asynchronous</b>. The system synchronizes Video RAM with your <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>, the cube's graphics engine draws to the display, and the display refreshes its pixels. All of these processes run concurrently, and "in the background" with respect to the game code you write.</p>
<p>The system can automatically optimize performance by overlapping many common operations. Typically, the cube's graphics engine runs concurrently with a game's code, and when you're drawing to multiple cubes, those cubes can all update their displays concurrently.</p>
<p>In the SDK, this concurrency is managed at a very high level with the <a class="el" href="class_sifteo_1_1_system.html#a3676c1bc1e5891a686d2646d0ec516c6" title="Draw the next frame.">Sifteo::System::paint()</a> and <a class="el" href="class_sifteo_1_1_system.html#a36d92c44328916f60f62abf63d2ee7bd" title="Wait for any previous paint() to finish.">Sifteo::System::finish()</a> API calls. In short, <em>paint</em> asks for some rendering to begin, and <em>finish</em> waits for it to complete. Unless your application has a specific reason to wait for the rendering to complete, however, it is not necessary to call <em>finish</em>.</p>
<p><a class="el" href="class_sifteo_1_1_system.html#a3676c1bc1e5891a686d2646d0ec516c6" title="Draw the next frame.">Sifteo::System::paint()</a> is backed by an internal <em>paint controller</em> which does a lot of work so you don't have to. Frame rate is automatically throttled. Even though each cube's graphics engine may internally be rendering at a different rate (as shown by the FPS display in Siftulator) your application sees a single frame rate, as measured by the rate at which <em>paint</em> calls complete. This rate will never be higher than 60 FPS or lower than 10 FPS, and usually it will match the frame rate of the slowest cube.</p>
<p>This is a simplified example timeline, showing one possible way that asynchronous rendering could occur:</p>
<div class="image">
<img src="concurrency.png" alt="concurrency.png"/>
</div>
<ol type="1">
<li>The system starts out idle</li>
<li>Game logic runs, and prepares the first frame for rendering.</li>
<li>Game code calls <a class="el" href="class_sifteo_1_1_system.html#a3676c1bc1e5891a686d2646d0ec516c6" title="Draw the next frame.">Sifteo::System::paint()</a></li>
<li>This begins asynchronously synchronizing each cube's Video RAM with the corresponding <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>. In the mean time, game logic begins working on the next frame.</li>
<li>After each cube receives its <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a> changes, it begins rendering. This process uses data from Video RAM and from Asset Flash to compose a scene on the Display.</li>
<li>In this example, the Game Logic completes before the cubes are finished rendering. The system limits how far ahead the application can get, by blocking it until the previous frame is complete.</li>
<li>When all cubes finish rendering, the application is unblocked, and we begin painting the second frame. In this example, there were no changes to Cube 1's display on the second frame, so it remains idle.</li>
<li>Likewise, the third frame begins rendering on Cube 1 once the second frame is finished. In this example, the third frame <em>only</em> includes changes to Cube 1.</li>
</ol>
<p>Note that reality is a little messier than this, since the system tries really hard to avoid blocking any one component unless it's absolutely necessary, and some latency is involved in communicating between the system and each cube. Because of this, no guarantees are made about exactly when <a class="el" href="class_sifteo_1_1_system.html#a3676c1bc1e5891a686d2646d0ec516c6" title="Draw the next frame.">Sifteo::System::paint()</a> returns, only about the average rate at which <em>paint</em> calls complete. If you need hard guarantees that synchronization and rendering have finished on every cube, use <a class="el" href="class_sifteo_1_1_system.html#a36d92c44328916f60f62abf63d2ee7bd" title="Wait for any previous paint() to finish.">Sifteo::System::finish()</a>.</p>
<h2>Graphics Modes</h2>
<p>Due to the very limited amount of Video RAM available, the graphics engine defines several distinct <em>modes</em>, which each define a different behavior for the engine and potentially a different layout for the contents of Video RAM. These modes include different combinations of tiled layers and sprites, as well as low-resolution frame-buffer modes and a few additional special-purpose modes.</p>
<p>Graphics modes are all mutually exclusive. Only a single mode may be active per-cube for a given call to <a class="el" href="class_sifteo_1_1_system.html#a3676c1bc1e5891a686d2646d0ec516c6" title="Draw the next frame.">Sifteo::System::paint()</a>, and that mode may interpret Video RAM in a way which wouldn't make sense in any other mode. It is common, however, for modes to define themselves as supersets of other modes. For example, the <b>BG0</b> and <b>BG0_BG1</b> modes are mutually exclusive, and you can only paint with one or the other. But BG0_BG1 is defined as a mode which extends the Video RAM layout and rendering model that was introduced by BG0. Other modes, like <b>BG2</b>, have a completely distinct Video RAM layout and rendering model. Even though you can't use both BG0 and BG2 at the same time, you could use them in rapid succession in order to render different portions of the screen.</p>
<p>Each of these modes fits into a consistent overall rendering framework that provides a few constants that you can rely on no matter which video mode you use:</p>
<div class="image">
<img src="gfx-modes.png" alt="gfx-modes.png"/>
</div>
<ul>
<li><b>Paint control</b> happens in the same way regardless of the active video mode. Some of the Video RAM is used for paint control.</li>
</ul>
<ul>
<li><b>Windowing</b> is a feature in which only a portion of the display is actually repainted. The mode renderers operate on one horizontal scanline of pixels at a time, so even when windowing is in use the entire horizontal width of the display must be redrawn. Windowing can be used to create letterbox effects, to render status bars, dialogue, etc.</li>
</ul>
<ul>
<li><b>Rotation</b> by a multiple of 90-degrees can be enabled as the very last step in the graphics pipeline, after all mode-specific drawing, and after windowing.</li>
</ul>
<p>These effects can be composed over the course of multiple paint/finish operations. For example:</p>
<div class="image">
<img src="rotated-windowing.png" alt="rotated-windowing.png"/>
</div>
<h2>Tiles</h2>
<p>In order to make the most efficient use of the uncompressed pixel data in each cube's Asset Flash, these pixels are grouped into 8x8-pixel <em>tiles</em> which are de-duplicated during <a class="el" href="asset_workflow.html">Asset Preparation</a>. Any tile in Asset Flash may be uniquely identified by a 16-bit index. These indices are much smaller to store and transmit than the raw pixel data for an image.</p>
<p>This diagram illustrates how our tiling strategy helps games run more efficiently:</p>
<div class="image">
<img src="tile-grid.png" alt="tile-grid.png"/>
</div>
<ol type="1">
<li>Asset images begin as lossless PNG files, stored on disk.</li>
<li>These PNGs are read in by <em>stir</em>, and chopped up into a grid of 8x8-pixel tiles.</li>
<li>Stir determines the smallest unique set of tiles that can represent all images in a particular <a class="el" href="struct_sifteo_1_1_asset_group.html" title="A bundle of compressed tile data, for use by AssetImages.">Sifteo::AssetGroup</a>. This step may optionally be lossy. (Stir can find or generate tiles that are "close enough" without being pixel-accurate.) These tiles are compressed further using a lossless codec, and included in your application's AssetGroup data.</li>
<li>The original asset is recreated as an array of indices into the AssetGroup's tiles. This data becomes a single <a class="el" href="struct_sifteo_1_1_asset_image.html" title="Any kind of asset image, as defined in your stir script.">Sifteo::AssetImage</a> object. The index data can be much smaller than the original image, and duplicated tiles can be encoded in very little space.</li>
<li>At runtime, AssetGroups and AssetImages are loaded separately. The former are loaded (slowly) into Asset Flash, whereas the latter are used by application code to draw into Video RAM.</li>
</ol>
<p>For more information on how assets are stored in memory, see <a class="el" href="asset_memory.html">Asset Memory Management</a>.</p>
<h1>Graphics Mode Reference</h1>
<h2>BG0</h2>
<p>This is the prototypical tile-based mode that many other modes are based on. The name is short for <em>background zero</em>, and you may find both the design and terminology familiar if you've ever worked on other tile-based video game systems. Many of the most popular 2D video game systems had hardware acceleration for one or more tile-based <em>background</em> layers.</p>
<p>BG0 is both the simplest mode and the most efficient. It makes good use of the hardware's fast paths, and it is quite common for BG0 rendering rates to exceed the physical refresh rate of the LCD.</p>
<p>The <a class="el" href="struct_sifteo_1_1_b_g0_drawable.html" title="A VRAM accessor for drawing graphics in the BG0 mode.">Sifteo::BG0Drawable</a> class understands the Video RAM layout used in BG0 mode. You can find an instance of this class as the <em>bg0</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<div class="image">
<img src="bg0-layer.png" alt="bg0-layer.png"/>
</div>
<p>In this mode there is a single layer, an infinitely-repeating 18x18 tile grid. Video RAM contains an array of 324 tile indices, each stored as a 16-bit integer. Under application control, the individual tiles in this grid can be freely defined, and the viewport may <em>pan</em> around the grid with single-pixel accuracy:</p>
<div class="image">
<img src="bg0-viewport.png" alt="bg0-viewport.png"/>
</div>
<p>If the panning coordinates are a multiple of 8 pixels, the BG0 tile grid is lined up with the edges of the display and you can see a 16x16 grid of whole tiles. If the panning coordinates are not a multiple of 8 pixels, the tiles on the borders of the display will be partially visible. Up to a 17x17 grid of (partial) tiles may be visible at any time. The 18th row/column can be used for advanced scrolling techniques that pre-load tile indices just before they pan into view. This so-called <em>infinite scrolling</em> technique can be used to implement menus, large side-scrolling maps, and so on.</p>
<h2>BG0_BG1</h2>
<p>Just as you might create several composited layers in a photo manipulation or illustration tool in order to move objects independently, the Sifteo graphics engine provides a simple form of layer compositing.</p>
<p>Sometimes you only need a single layer. Since you can modify each tile index independently in BG0, any animation is possible as long as objects move in 8-pixel increments, or the entire BG0 layer can move as a single unit. But sometimes it's invaluable to have even a single object that "breaks the grid" and moves independently. In the <b>BG0_BG1</b> mode, a second <em>background one</em> layer floats on top of BG0. You might use this for:</p>
<ul>
<li>Explanatory text that pops up over a scene</li>
<li>Parallax scrolling, where differents parts of the scene scroll at different rates to simulate depth</li>
<li>A scoreboard, overlaid on your game's playfield</li>
<li>Large movable objects, like enemies or menu icons, which scroll against a static background</li>
</ul>
<p>Like BG0, BG1 is defined as a grid of tile indices. You can combine any number of Asset Images when drawing BG1, as long as everything is aligned to the 8-pixel tile grid. But BG0 and BG1 use two independent grid systems; you can pan each layer independently. Additionally, BG1 implements 1-bit transparency. Pixels on BG1 which are at least 50% transparent will allow BG0 to show through. Note that Sifteo Cubes do not provide any alpha blending, so all pixels that are at least 50% opaque appear as fully opaque.</p>
<div class="image">
<img src="bg1-stackup.png" alt="bg1-stackup.png"/>
</div>
<p>In this example, BG0 contains a side-scrolling level, and BG1 contains both a player avatar and a score meter. The avatar and score meter are stationary on the screen, so we don't need to make use of BG1's pixel-panning feature. By panning BG0, the level background can scroll left and give the appearance that the player is walking right. The tiles underlying the player sprite and the score meter can be independently replaced, in order to animate the player or change the score.</p>
<p>The amount of RAM available for BG1 is quite limited. Unfortunately, the Video RAM in each Sifteo Cube is too small to include two 18x18 grids as used by BG0. The space available to BG1 is only sufficient for a total of 144 tiles, or about 56% of the screen.</p>
<p>To overcome this limitation, BG1 is arranged as a 16x16 tile non-repeating <em>virtual grid</em> which can be backed by up to 144 tiles. This means that at least 112 tiles in this virtual grid must be left unallocated. Unallocated tiles always appear fully transparent.</p>
<p>Pixel panning, when applied to BG1, always describes the offset between the top-left corner of the virtual grid and the top-left corner of the display window. This means that the physical location of any tile depends both on the current pixel panning and on the tile's location in the virtual grid.</p>
<p>Tile allocation is managed by a <b>mask</b> bitmap. Each tile in the virtual grid has a single corresponding bit in the mask. If the bit is 0, the tile is unallocated and fully transparent. If the bit is 1, that location on the virtual grid is assigned to the next available tile index in the 144-tile array. Array locations are always assigned by scanning the mask bitmap from left-to-right and top-to-bottom.</p>
<div class="image">
<img src="bg1-layer.png" alt="bg1-layer.png"/>
</div>
<p>The <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html" title="A VRAM accessor for drawing graphics in the BG1 mode.">Sifteo::BG1Drawable</a> class understands the Video RAM layout used for the BG1 layer in <b>BG0_BG1</b> mode. You can find an instance of this class as the <em>bg1</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<p>This class provides several distinct methods to set up the mask and draw images to BG1. Depending on your application, it may be easiest to set up the mask by:</p>
<ol type="1">
<li>Allocating tiles one row at a time, using <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#a89fe17837b494d916f0234523c7d0198" title="Erase just the allocation mask. All tiles will now be unallocated, and BG1 will be fully transparent...">Sifteo::BG1Drawable::eraseMask()</a> and <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#a90de1df00dbb4cd1c891ad18288a7f6f" title="This is a specialized alternative to setMask(), for cases where each row of BG1 has a single contiguo...">Sifteo::BG1Drawable::fillMask()</a>.</li>
<li>Composing an entire mask at compile-time using <a class="el" href="struct_sifteo_1_1_b_g1_mask.html" title="A BG1 tile mask. In other words, this is a 16x16-bit two-dimensional vector.">Sifteo::BG1Mask</a>, and applying it with <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#aa882eda876812923a7c2e5c7aa75e920" title="Change the tile allocation bitmap.">Sifteo::BG1Drawable::setMask()</a>.</li>
<li>Modifying a <a class="el" href="struct_sifteo_1_1_b_g1_mask.html" title="A BG1 tile mask. In other words, this is a 16x16-bit two-dimensional vector.">Sifteo::BG1Mask</a> at runtime, and applying it with <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#aa882eda876812923a7c2e5c7aa75e920" title="Change the tile allocation bitmap.">Sifteo::BG1Drawable::setMask()</a>.</li>
</ol>
<p>There are similarly multiple ways to draw the image data, after you've allocated tiles:</p>
<ol type="1">
<li>Use a raw <em>locationIndex</em> to plot individual values on the 144-tile array, with <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#aca3ae5972d58d2236e6541d5e7a6767e" title="Plot a single tile, by absolute tile index, at a specific location in the 144-tile array...">Sifteo::BG1Drawable::plot()</a> and <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#af38cfcf6ac8cc513c3c60fa561d665b5" title="Plot a horizontal span of tiles in consecutively allocated locations in the BG1 tile array...">Sifteo::BG1Drawable::span()</a>.</li>
<li>Use <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#a8926d9bd9fa361bed0545053b1f76257" title="Draw a full AssetImage frame, with its top-left corner at the specified location.">Sifteo::BG1Drawable::image()</a> to draw a <a class="el" href="struct_sifteo_1_1_asset_image.html" title="Any kind of asset image, as defined in your stir script.">Sifteo::AssetImage</a>, automatically <em>clipping</em> it to the allocated subset of the virtual grid, and automatically calculating the proper <em>locationIndex</em> for each tile.</li>
<li>Use <a class="el" href="struct_sifteo_1_1_b_g1_drawable.html#a932f2739ebaeae983f25679ed648faf2" title="Draw an AssetImage, automatically allocating tiles on the BG1 mask.">Sifteo::BG1Drawable::maskedImage()</a> to set the mask and draw an image in one step.</li>
</ol>
<h2>BG0_SPR_BG1</h2>
<p>Sometimes two independently-movable layers really just isn't enough. This mode adds up to <b>eight sprites</b> per cube, which float in-between BG0 and BG1. Each sprite can be moved fully independently. This, as you can imagine, offers a lot of flexibility. Sprites are great for particle effects, items, characters, and all manner of other doodads.</p>
<p>Sprites have a <em>priority</em> according to their index in the sprite array, from 0 to 7. Lower-numbered sprites are higher priority, and appear above higher-numbered sprites. In other words, each sprite is tested in ascending numerical order until the first opaque pixel is found.</p>
<div class="image">
<img src="spr-stackup.png" alt="spr-stackup.png"/>
</div>
<p>All of this power comes with a handful of caveats, however:</p>
<ul>
<li>Each sprite's width and height must both be powers of two.</li>
<li>Sprites are still made of tiles, so they must also be at least 8x8 pixels.</li>
<li>At most four sprites may appear on the same horizontal row of pixels. If more than four sprites share a scanline, the additional sprites will not be drawn on the affected lines.</li>
<li>Sprites can be much slower than BG0 or BG1, especially when they are large, you have many overlapping sprites, or there are large transparent regions.</li>
<li>Sprites are not backed by tile grids like BG0 and BG1 are. You can specify the index of the top-left tile in the sprite, but all other tiles are assumed to be sequential. This necessitates the use of a <a class="el" href="struct_sifteo_1_1_pinned_asset_image.html" title="An AssetImage in which all tiles are stored sequentially in memory.">Sifteo::PinnedAssetImage</a>, created by setting <em>pinned=true</em> in your <a class="el" href="asset_workflow.html">stir</a> script.</li>
<li>Because sprites require pinned assets, sprite images typically require much more storage space than images which are only displayed on tiled layers like BG0 or BG1.</li>
</ul>
<p>The <a class="el" href="struct_sifteo_1_1_sprite_layer.html" title="A SpriteLayer represents the VRAM attributes for the sprite rendering layer in BG0_SPR_BG1 mode...">Sifteo::SpriteLayer</a> class understands the Video RAM layout used for the sprites in <b>BG0_SPR_BG1</b> mode. You can find an instance of this class as the <em>sprites</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<h2>BG2</h2>
<p>So far, we've been talking a lot about repositioning layers and editing tile grids, but none about common modern graphical operations like rotation, scaling, and blending. This stems from the underlying technical strengths and weaknesses of a platform as small and power-efficient as Sifteo Cubes. It's very efficient to pan a layer or manipulate tiles, but quite inefficient to do the kinds of operations you may be familiar with from toolkits like OpenGL. Modern GPUs are very good at using mathematical matrices to transform objects, but they're also very expensive and very power-hungry! The above video modes are much better at getting the most from our tiny graphics engine.</p>
<p>Nevertheless, sometimes you really do need to rotate or scale an image for that one special effect. Even a little bit of image transformation can make the difference between a clunky transition and a really polished interstitial animation. This is where the <b>BG2</b> mode can help.</p>
<p>BG2 consists of a <b>16x16 tile grid</b> and a matrix which applies a single <b>affine transform</b> to the entire scene. The layer does repeat every 256 pixels horizontally and vertically, due to 8-bit integer wraparound, but the unused portions of this 256x256 space are painted with a solid-color <em>border</em>. This makes it possible to scale a full-screen image down by up to 1/2 without seeing any repeats.</p>
<div class="image">
<img src="bg2-layer.png" alt="bg2-layer.png"/>
</div>
<p>The entire layer is transformed via a <a class="el" href="struct_sifteo_1_1_affine_matrix.html" title="An augmented 3x2 matrix, for doing 2D affine transforms.">Sifteo::AffineMatrix</a> which is used by the graphics engine to convert screen coordinates into virtual coordinates in this repeating 256x256-pixel space:</p>
<div class="image">
<img src="bg2-matrix.png" alt="bg2-matrix.png"/>
</div>
<p>You can think of this matrix as a set of instructions for the rendering engine:</p>
<ul>
<li>Start at virtual coordinate (cx, cy)</li>
<li>For every horizontal pixel on the display, add (xx, xy) to the virtual coordinate.</li>
<li>For every vertical row of the display, add (yx, yy) to the virtual coordinate for the beginning of that row.</li>
</ul>
<div class="image">
<img src="bg2-transform.png" alt="bg2-transform.png"/>
</div>
<p>The <a class="el" href="struct_sifteo_1_1_b_g2_drawable.html" title="A VRAM accessor for drawing graphics in the BG2 mode.">Sifteo::BG2Drawable</a> class understands the Video RAM layout used in the BG2 mode. You can find an instance of this class as the <em>bg2</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<p>There are a few technical limitations and caveats, of course:</p>
<ul>
<li>No other layers may be combined with BG2. Specifically, sprites are not available in BG2 mode.</li>
<li>The graphics engine does not include any filtering, it just rounds virtual coordinates to the nearest integer pixel. This means that the scaling quality is inherently low, so it's best for quick transitions or special effects rather than for images that the user spends a lot of time seeing.</li>
<li>The BG2 renderer includes an optimization which works by updating the virtual Y coordinate less frequently than the X coordinate. This means that rotation quality decreases as the angle gets closer to 90 degrees. For this reason, we strongly recommend that rotations near 90 degrees are not performed using the BG2 affine transform. One workaround is to use the mode-independent display rotation to get to the nearest 90-degree multiple, then use BG2 for the remainder of the rotation angle.</li>
<li>The affine matrix is stored in Video RAM as an array of six signed 16-bit fixed point numbers in <em>8.8</em> format. In other words, there are always 8 bits to the left of the binary point and 8 bits to the right of the binary point. The <a class="el" href="struct_sifteo_1_1_affine_matrix.html" title="An augmented 3x2 matrix, for doing 2D affine transforms.">Sifteo::AffineMatrix</a> class uses floating point numbers, however, so typically you won't have to deal with fixed point values yourself.</li>
</ul>
<h2>BG0_ROM</h2>
<p>All of the video modes we've discussed so far are based on assembling pixel data that has been previously stored to Asset Flash. But what if you can't count on the contents of Asset Flash? This could be the case in debugging or error handling code, or during early bootstrapping.</p>
<p>For these situations, the graphics engine provides the <b>BG0_ROM</b> mode. It is identical to the BG0 mode, except that tile data comes from an internal read-only memory region in the Sifteo Cube hardware. These tile images are installed during manufacturing, and they cannot be modified. This makes the BG0_ROM mode of limited usefulness for most applications.</p>
<p>The ROM tileset does, however, include an 8x8 fixed-width font. This system font can be really handy for debugging, diagnostics, and prototyping. For example, the <em>sensors</em> demo uses this mode as a quick way to display text:</p>
<div class="image">
<img src="sensors.png" alt="sensors.png"/>
</div>
<p>Tile indices in this mode are 14 bits, divided into a few distinct fields which control the rendering process on a per-tile basis:</p>
<ul>
<li>Nine bits are used for a tile index. The ROM has space for up to 512 two-color tiles.</li>
<li>One bit enables four-color mode, in which two adjacent two-color tiles are reinterpreted as two bit planes which combine to form a single four-color tile.</li>
<li>Four bits select one of sixteen color palettes, also stored in ROM.</li>
</ul>
<p>The <a class="el" href="struct_sifteo_1_1_b_g0_r_o_m_drawable.html" title="A VRAM accessor for drawing graphics in the BG0_ROM mode.">Sifteo::BG0ROMDrawable</a> class understands the Video RAM layout used in the BG0_ROM mode, plus it understands the ROM tileset layout enough to draw text and progress bars. You can find an instance of this class as the <em>bg0rom</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<dl class="section warning"><dt>Warning</dt><dd>Currently the ROM tileset artwork has not been finalized, so applications must not rely on specific tile indices. It is important to use only the public functions in <a class="el" href="struct_sifteo_1_1_b_g0_r_o_m_drawable.html" title="A VRAM accessor for drawing graphics in the BG0_ROM mode.">Sifteo::BG0ROMDrawable</a>.</dd></dl>
<h2>SOLID</h2>
<p>The simplest video mode! It draws a single solid color, from the first entry in the <a class="el" href="struct_sifteo_1_1_colormap.html" title="An accessor for the colormap, with up to 16 colors.">Sifteo::Colormap</a>. The colormap holds up to 16 colors in RGB565 format. You can find an instance of this class as the <em>colormap</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<p>This mode can be used as a building block for advanced visual effects. When using windowing techniques to create a letterbox effect, for example, the SOLID mode can be used to paint a solid-color background. You can also use the SOLID mode to create bright flashes, wipes, and so on.</p>
<p>Unlike the tiled modes above, the SOLID mode uses <a class="el" href="struct_sifteo_1_1_colormap.html" title="An accessor for the colormap, with up to 16 colors.">Sifteo::Colormap</a> and therefore any RGB565 color can be chosen at runtime.</p>
<p>The SOLID mode also has the advantage of using very little space in a cube's Video RAM. You can set up the necessary parameters for this mode very quickly, using only a small amount of radio traffic.</p>
<h2>FB32</h2>
<p>You might be wondering: Why do we need this Asset Flash memory at all? Can't we just send some pixels over the radio, and draw directly to a Sifteo Cube's display?</p>
<p>The answer: Kind of. Unfortunately, a complete framebuffer for our 128x128 16-bit display would require 32 kB of RAM, which is quite large on this system. It's much larger than the 1 kB available for each cube's Video RAM. Additionally, it would be slow to send this framebuffer image over the radio. This is a big part of why the graphics engine prefers to work with tile indices. There are so many fewer tile indices than pixels!</p>
<p>That said, sometimes you really do just want to draw arbitrary pixels to the screen. The graphics engine includes a small set of <b>framebuffer modes</b> which compromise by providing low-resolution and low-color-depth modes which do fit in the limited memory available.</p>
<p>The <b>FB32</b> mode is a 32x32 pixel 16-color framebuffer. It requires 512 bytes of RAM, or exactly half of the Video RAM. The other half includes mode-independent data, as well as a colormap which acts as a lookup table to convert each of these 16 colors into a full RGB565 color. This 32x32 <em>chunky-pixel</em> image is scaled up by a factor of four by the mode renderer.</p>
<div class="image">
<img src="otto.png" alt="otto.png"/>
</div>
<p>The <a class="el" href="struct_sifteo_1_1_f_b_drawable.html" title="A templatized VRAM accessor for drawing pixel graphics, in one of the cube&#39;s supported framebuffer dr...">Sifteo::FBDrawable</a> template implements Video RAM accessors for plotting individual pixels, filling rectangles, and blitting bitmaps on to the framebuffer. Sifteo::FB32Drawable is a typedef for the specialization of this template used in FB32 mode, and you can find an instance of this class as the <em>fb32</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<p>The 16-entry colormap can be independently accessed via <a class="el" href="struct_sifteo_1_1_colormap.html" title="An accessor for the colormap, with up to 16 colors.">Sifteo::Colormap</a>, which lives in the <em>colormap</em> member of <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>. The colormap can be modified either before or after plotting pixel data. By changing the colors associated with each color index, you can perform palette animation efficiently without changing any of the underlying framebuffer memory.</p>
<dl class="section note"><dt>Note</dt><dd>Due to details of the compression used to update Video RAM over the air, it's more efficient to use even color indices than odd indices. You can optimize to take advantage of this fact by placing the most commonly used colors at even indices in the <a class="el" href="struct_sifteo_1_1_colormap.html" title="An accessor for the colormap, with up to 16 colors.">Sifteo::Colormap</a>.</dd></dl>
<h2>FB64</h2>
<p>The <b>FB64</b> mode is another flavor of framebuffer, but this time with a different resolution vs. color depth tradeoff. It stores data for a 64x64 pixel framebuffer, which is doubled to 128x128 during rendering. However, this only leaves memory for 1 bit per pixel, or 2 colors.</p>
<p>This mode uses the <a class="el" href="struct_sifteo_1_1_f_b_drawable.html" title="A templatized VRAM accessor for drawing pixel graphics, in one of the cube&#39;s supported framebuffer dr...">Sifteo::FBDrawable</a> template as well. Sifteo::FB64Drawable is a typedef for the specialization of this template used in FB64 mode, and you can find an instance of this class as the <em>fb64</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<p>Only the first two entries of <a class="el" href="struct_sifteo_1_1_colormap.html" title="An accessor for the colormap, with up to 16 colors.">Sifteo::Colormap</a> are used. The colormap lives in the <em>colormap</em> member of <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<h2>FB128</h2>
<p>The last of our pure framebuffer modes is <b>FB128</b>. As the name would imply, it is 128 pixels wide. Like <b>FB64</b>, it is 1 bit per pixel. (2-color)</p>
<p>This framebuffer mode does not employ any scaling. Each pixel maps directly to one pixel on the display. This makes it a much more generally useful mode, but at a cost: There is only enough RAM for 48 rows of pixels. FB128 is a <b>128x48</b> pixel mode which is repeated vertically if the display window is more than 48 rows high.</p>
<p>The FB128 mode is particularly useful for text rendering, since it is the most efficient way to display fonts with proportional spacing. The SDK includes a <b>text</b> example which makes use of the SOLID and FB128 modes:</p>
<div class="image">
<img src="text-example.png" alt="text-example.png"/>
</div>
<p>This mode uses the <a class="el" href="struct_sifteo_1_1_f_b_drawable.html" title="A templatized VRAM accessor for drawing pixel graphics, in one of the cube&#39;s supported framebuffer dr...">Sifteo::FBDrawable</a> template as well. Sifteo::FB128Drawable is a typedef for the specialization of this template used in FB128 mode, and you can find an instance of this class as the <em>fb128</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<p>Only the first two entries of <a class="el" href="struct_sifteo_1_1_colormap.html" title="An accessor for the colormap, with up to 16 colors.">Sifteo::Colormap</a> are used. The colormap lives in the <em>colormap</em> member of <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>.</p>
<h2>STAMP</h2>
<p>The <b>STAMP</b> mode is a special-purpose framebuffer which supports tiling, two-dimensional windowing, and 1-bit <em>color key</em> transparency. Like its rubber namesake, this stamp is good at splatting images on top of other images.</p>
<p>This mode is intended for various special effects which prefer to operate in <em>immediate mode</em>. Instead of composing a full scene in Video RAM and drawing it all in one pass, <em>immediate mode</em> refers to the technique of drawing only a small part of the scene during each hardware "frame". This is analogous to other rendering models you may be familiar with, such as OpenGL, in which each primitive is independently drawn to the screen.</p>
<p>There are some important downsides to immediate mode rendering which typically make it inferior to the tile-based video modes above:</p>
<ul>
<li>It is <b>slower</b>, because the Sifteo Cube hardware is not optimized for the performance of modes like STAMP.</li>
<li>It is not double-buffered: you're drawing directly to the same display memory which is scanned out to the LCD. So, most forms of animation will be accompanied with some amount of <b>flickering</b>.</li>
</ul>
<p>Nevertheless, this mode can be invaluable for certain kinds of special effects. Anything that builds up a scene gradually, such as a painting game, may use the STAMP mode as its <em>brush</em>. You can use this mode for full-screen stippling effects, for simulating fade-out. This mode may also be useful for text overlays.</p>
<p>The <em>STAMP</em> mode allows a portion of Video RAM to be interpreted as a framebuffer with variable dimensions. Any size may be used, as long as the width is even (making it an integral number of bytes) and the total number of pixels is less than or equal to <b>1536</b>. For example, you could use a 128x12 framebuffer, or 64x24, or 32x32.</p>
<p>Just like the FB32 mode, we use a 16-entry color lookup table. This can be accessed via <a class="el" href="struct_sifteo_1_1_colormap.html" title="An accessor for the colormap, with up to 16 colors.">Sifteo::Colormap</a>, which lives in the <em>colormap</em> member of <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>. One of these colormap indices may optionally be designated as the transparent "key" index. Any pixels matching that index will be skipped entirely rather than drawn to the framebuffer.</p>
<p>This small framebuffer repeats in both axes, just like in FB128 mode. Horizontal windowing may be used to restrict the rendering area to a box equal in size to the framebuffer. In this usage, STAMP mode can be used much like sprites, but without erasing any drawing already present on the display. If the box is smaller, the framebuffer is cropped. If it's larger, the framebuffer repeats.</p>
<div class="image">
<img src="stampy.png" alt="stampy.png"/>
</div>
<p>The <b>stampy</b> SDK example uses this video mode both to draw a sprite-like character bouncing around the screen, and to use a time-variant stipple pattern in order to "dissolve" the trail of images that is left behind as the character bounces.</p>
<p>The <a class="el" href="struct_sifteo_1_1_stamp_drawable.html" title="A VRAM accessor for the STAMP mode, a special purpose 16-color framebuffer mode which supports color-...">Sifteo::StampDrawable</a> object acts as an accessor for the STAMP mode's horizontal windowing and color-keying parameters. You can find an instance of this class as the <em>stamp</em> member inside <a class="el" href="struct_sifteo_1_1_video_buffer.html" title="A memory buffer which holds graphics data.">Sifteo::VideoBuffer</a>. It provides accessors which retrieve a <a class="el" href="struct_sifteo_1_1_f_b_drawable.html" title="A templatized VRAM accessor for drawing pixel graphics, in one of the cube&#39;s supported framebuffer dr...">Sifteo::FBDrawable</a> instance of the right geometry, which you may use to draw pixel data to the mode's framebuffer memory. </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.3.1-->
<!-- start footer part -->
    <hr class="footer"/>
    <address class="footer">
        <p><a href="http://sifteo.com">Sifteo</a> SDK v1.0.0 <small>(see <a href="https://developers.sifteo.com/sifteosdk">all versions</a>)</small></p>
        <p>Last updated Wed Mar 27 2013, by <a href="http://www.stack.nl/~dimitri/doxygen">Doxygen</a></p>
    </address>
</body>
</html>
